import blue
import trinity
import paperDoll as PD
import uthread
import weakref
import random
import stackless
import log
import sys
import util
import loadRequest
LoadingStubPath = 'res:/Graphics/Character/Global/LowLODs/Female/BasicFemale/BasicFemale.red'
LoadingStubPathExterior = 'res:/Graphics/Character/Global/LowLODs/Female/BasicFemale/BasicFemaleExterior.red'
TEXTURE_SIZES = [(2048, 1024),
 (512, 256),
 (256, 128)]

class BuildRequest(loadRequest.PrioritizedLoadRequest):

    def __init__(self, doll, callingProxy, visual, data):
        loadRequest.PrioritizedLoadRequest.__init__(self)
        self.doll = doll
        self.callingProxy = callingProxy
        self.visual = visual
        self.data = data



    def GetName(self):
        return 'PaperDoll'



    def GetPriority(self):
        return self.data.avatar.estimatedPixelDiameter



    def Process(self):
        doll = self.doll
        callingProxy = self.callingProxy
        visual = self.visual
        data = self.data
        if (data.lod == 0):
            doll.SetTextureSize(2048, 1024)
        elif (data.lod == 1):
            doll.SetTextureSize(512, 256)
        elif (data.lod == 2):
            doll.SetTextureSize(256, 128)
        doll.overrideLod = data.lod
        if (data.doll.overrideLod == 1232):
            if (newVisual is None):
                data.doll.Update(data.dollFactory, avatar=data.avatar, visualModel=visual, LODMode=True)
            else:
                visual = newVisual
                data.doll.Update(data.dollFactory, visualModel=newVisual, LODMode=True)
        else:
            data.doll.Update(data.dollFactory, avatar=data.avatar, visualModel=visual, LODMode=True)
        if trinity.settings.GetValue('debugLODShader'):
            path = 'res:/Graphics/Effect/Managed/Visualizer/AvatarLOD0.fx'
            if (data.doll.overrideLod == 1):
                path = 'res:/Graphics/Effect/Managed/Visualizer/AvatarLOD1.fx'
            elif (data.doll.overrideLod == 2):
                path = 'res:/Graphics/Effect/Managed/Visualizer/AvatarLOD2.fx'
            for mesh in visual.meshes:
                fx = mesh.Find('trinity.Tr2Effect')
                for f in iter(fx):
                    f.effectFilePath = path


        if (callingProxy is not None):
            while data.doll.IsBusyUpdating():
                blue.synchro.Yield()

            callingProxy.SetObjectFromBuilder(visual)
            callingProxy.temporary = False
            data.threads[callingProxy] = None




def CreateVisualForDoll(doll):
    gender = doll.gender
    visual = trinity.Tr2SkinnedModel()
    visual.skinScale = (1.0, 1.0, 1.0)
    if (gender == PD.GENDER.FEMALE):
        visual.geometryResPath = const.DEFAULT_FEMALE_PAPERDOLL_MODEL
    else:
        visual.geometryResPath = const.DEFAULT_MALE_PAPERDOLL_MODEL
    visual.name = gender
    visual.skeletonName = 'Root'
    return visual



def MakeTrinityLoadBuilder(path):

    def CreateClosure(path, objectMarker, callingProxy):
        visual = trinity.Load(path)
        if ((visual is not None) and hasattr(visual, 'visualModel')):
            visual = visual.visualModel
        return visual


    builder = blue.BlueObjectBuilderPython()
    builder.SetCreateMethod(lambda objectMarker, callingProxy: CreateClosure(path, objectMarker, callingProxy))
    return builder



def MakePaperdollBuilder(avatar, doll, lod, dollFactory, dollAnimation, stub = None):

    class DataHelper():


    def CreateClosure(data, objectMarker, callingProxy):
        if (callingProxy is not None):
            callingProxy.temporary = True
        visual = CreateVisualForDoll(data.doll)
        request = BuildRequest(doll, callingProxy, visual, data)
        sm.GetService('prioritizedLoadManager').Add(callingProxy, request)
        return visual



    def CreateAsyncClosure(data, objectMarker, callingProxy):
        callingProxy.temporary = True
        visual = data.stub
        if (visual is None):
            return CreateClosure(data, objectMarker, callingProxy)
        else:
            if hasattr(visual, 'visualModel'):
                visual = visual.visualModel
            uthread.new(CreateClosure, data, objectMarker, callingProxy)
            return visual



    def OnDestroyClosure(data, objectMarker, callingProxy):
        sm.GetService('prioritizedLoadManager').Cancel(callingProxy)
        callingProxy.SetObjectFromBuilder(None)
        callingProxy.temporary = False


    builder = blue.BlueObjectBuilderPython()
    data = DataHelper()
    data.avatar = avatar
    data.doll = doll
    data.lod = lod
    data.dollFactory = dollFactory
    data.dollAnimation = dollAnimation
    data.builder = weakref.ref(builder)
    data.threads = {}
    if (stub is None):
        builder.SetCreateMethod(lambda objectMarker, callingProxy: CreateClosure(data, objectMarker, callingProxy))
    else:
        data.stub = stub
        builder.SetCreateMethod(lambda objectMarker, callingProxy: CreateAsyncClosure(data, objectMarker, callingProxy))
    builder.SetDestroyHandler(lambda objectMarker, callingProxy: OnDestroyClosure(data, objectMarker, callingProxy))
    return builder



def SetupLODFromPaperdoll(avatar, doll, factory, animation, loadStub = True):
    if ((doll is None) or (avatar is None)):
        return 
    stub = None
    if loadStub:
        if (avatar.__bluetype__ == 'trinity.Tr2IntSkinnedObject'):
            stub = blue.os.LoadObject(LoadingStubPath)
        else:
            stub = blue.os.LoadObject(LoadingStubPathExterior)
    if hasattr(stub, 'visualModel'):
        stub = stub.visualModel

    class InPlaceBuilder():

        def __init__(self, avatar, doll, factory, stub):
            self.avatar = blue.BluePythonWeakRef(avatar)
            self.doll = weakref.ref(doll)
            self.factory = weakref.ref(factory)

            def MakeBuilder(lod):
                lodBuilder = blue.BlueObjectBuilderPython()
                lodBuilder.SetCreateMethod(lambda objectMarker, callingProxy: self.DoCreate(callingProxy, lod))
                lodBuilder.SetSelectedHandler(lambda objectMarker, callingProxy: self.OnSelected(callingProxy, lod))
                proxy = blue.BlueObjectProxy()
                proxy.builder = lodBuilder
                return proxy


            avatar.highDetailModel = MakeBuilder(0)
            avatar.mediumDetailModel = MakeBuilder(1)
            avatar.lowDetailModel = MakeBuilder(2)
            factory.AppendMeshesToVisualModel(avatar.visualModel, stub.meshes)



        def DoCreate(self, callingProxy, lod):
            if (self.avatar.object is None):
                return 
            else:
                return self.avatar.object.visualModel



        def OnSelected(self, callingProxy, lod):
            doll = self.doll()
            factory = self.factory()
            avatar = self.avatar.object
            if ((doll is None) or ((factory is None) or (avatar is None))):
                return 
            if (doll.overrideLod != lod):
                doll.overrideLod = lod
                doll.SetTextureSize(*TEXTURE_SIZES[lod])
            uthread.new(doll.Update, factory, avatar)



    simpleBuilder = InPlaceBuilder(avatar, doll, factory, stub)



def AbortAllLod(avatar):
    if (avatar is None):
        return 
    if (avatar.highDetailModel is not None):
        avatar.highDetailModel.object = None
    if (avatar.mediumDetailModel is not None):
        avatar.mediumDetailModel.object = None
    if (avatar.lowDetailModel is not None):
        avatar.lowDetailModel.object = None


exports = util.AutoExports('paperDoll', globals())

